package sartoservicesync.connectors;

import java.io.StringWriter;
import java.net.Authenticator;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.core.MultivaluedMap;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import sartoservicesync.entities.presta.PrestaCategory;
import sartoservicesync.entities.presta.PrestaCustomer;
import sartoservicesync.entities.presta.PrestaEntity;
import sartoservicesync.entities.presta.PrestaProduct;
import sartoservicesync.entities.presta.PrestaTag;
import sartoservicesync.entities.presta.wrapper.PrestaCategoriesWrapper;
import sartoservicesync.entities.presta.wrapper.PrestaCustomerWrapper;
import sartoservicesync.entities.presta.wrapper.PrestaCustomersWrapper;
import sartoservicesync.entities.presta.wrapper.PrestaMultiObjectWrapper;
import sartoservicesync.entities.presta.wrapper.PrestaProductsWrapper;
import sartoservicesync.entities.presta.wrapper.PrestaSingleObjectWrapper;
import sartoservicesync.entities.presta.wrapper.PrestaTagWrapper;
import sartoservicesync.entities.presta.wrapper.PrestaWrapper;
import sartoservicesync.utils.PrestaAuthenticator;
import sartoservicesync.utils.PrestaConstants;
import sartoservicesync.utils.PrestaWebservice;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.filter.LoggingFilter;
import com.sun.jersey.core.util.MultivaluedMapImpl;

public class PrestaConnector {
	static final Logger logger = LoggerFactory.getLogger(PrestaConnector.class);

	public List<PrestaCategory> loadFullCategoriesList() {
		PrestaCategoriesWrapper w = new PrestaCategoriesWrapper();
		w = (PrestaCategoriesWrapper) loadEntities(w,
				PrestaWebservice.CATEGORIES_LIST);
		return (List<PrestaCategory>) w.getResourceList();
	}

	public List<PrestaProduct> loadFullProductList() {
		PrestaProductsWrapper w = new PrestaProductsWrapper();
		w = (PrestaProductsWrapper) loadEntities(w,
				PrestaWebservice.PRODUCTS_LIST);
		return (List<PrestaProduct>) w.getResourceList();
	}

	public List<PrestaCustomer> loadFullCustomersList() {
		PrestaCustomersWrapper w = new PrestaCustomersWrapper();
		w = (PrestaCustomersWrapper) loadEntities(w,
				PrestaWebservice.CUSTOMERS_LIST);
		return (List<PrestaCustomer>) w.getResourceList();
	}

	private PrestaWrapper loadEntities(PrestaWrapper wrapper,
			PrestaWebservice webservice) {
		List<PrestaEntity> result = new ArrayList<PrestaEntity>();
		logger.debug("Lade {} aus dem Bienenkorb-Prestashop System",
				webservice.getEntityName());
		logger.trace("URL: {}", webservice.getUrl());
		long startTime = System.currentTimeMillis();
		Client client = Client.create();
		Authenticator.setDefault(new PrestaAuthenticator(webservice.getKey()));
		WebResource webResource = client.resource(webservice.getUrl());
		wrapper = webResource.get(wrapper.getClass());
		long duration = System.currentTimeMillis() - startTime;
		if (wrapper instanceof PrestaSingleObjectWrapper) {
			logger.debug("{} geladen in {}ms", webservice.getEntityName(),
					 duration);
		} else if (wrapper instanceof PrestaMultiObjectWrapper) {
			if (logger.isTraceEnabled()) {
				for (PrestaEntity ent : ((PrestaMultiObjectWrapper) wrapper)
						.getResourceList()) {
					logger.trace(ent.toString());
				}
			}
			logger.debug("{} {} geladen in {}ms",
					((PrestaMultiObjectWrapper) wrapper).getResourceList()
					.size(), webservice.getEntityName(), duration);
		} else {
			logger.error("Unbekannter Wrapper - keine Daten geladen");
		}

		return wrapper;
	}

	public PrestaCustomer getRakutenCustomer() {
		PrestaCustomer result = null;
		List<PrestaEntity> list = null;// loadEntities(new
										// PrestaCustomersWrapper(),
		// PrestaWebservice.RAKUTENCUSTOMER);
		if (list.size() != 1) {
			switch (list.size()) {
			case 0:
				createRakutenCustomer();
				break;
			default:
				logger.error("insgesamt {} {} gefunden!!!", list.size(),
						PrestaWebservice.RAKUTEN_CUSTOMER.getEntityName());
				break;
			}
		} else {
			result = (PrestaCustomer) list.get(0);
		}
		return result;
	}

	private PrestaCustomer createRakutenCustomer() {

		String entityName = PrestaWebservice.RAKUTEN_CUSTOMER.getEntityName();
		logger.debug("{} nicht gefunden, wird neu erstellt", entityName);
		PrestaCustomerWrapper wrapper = new PrestaCustomerWrapper();
		// PrestaCustomer c = (PrestaCustomer) loadEntities(wrapper,
		// PrestaWebservice.EMPTYCUSTOMER).get(0);
		PrestaCustomer c = new PrestaCustomer();
		c.setFirstname(PrestaConstants.RAKUTEN_CUSTOMER_FIRSTNAME.toString());
		c.setLastname(PrestaConstants.RAKUTEN_CUSTOMER_LASTNAME.toString());
		c.setEmail(PrestaConstants.RAKUTEN_CUSTOMER_EMAIL.toString());
		c.setPasswd(PrestaConstants.RAKUTEN_CUSTOMER_PASSWORD.toString());
		c.setActive("1");
//		wrapper.setResource(c);
		try {
			createEntity(PrestaWebservice.CREATE_CUSTOMER, wrapper);
			logger.debug("{} erfolgreich erstellt", entityName);
		} catch (Exception e) {
			logger.error("{} konnte nicht erstellt werden: {}", entityName,
					e.getMessage());
		}
		return c;
	}

	private PrestaWrapper createEntity(
			PrestaWebservice webservice, PrestaSingleObjectWrapper wrapper)
			throws URISyntaxException, JAXBException {
		Client client = Client.create();
		Authenticator.setDefault(new PrestaAuthenticator(webservice.getKey()));
		WebResource webResource = client.resource(webservice.getUrl());
		JAXBContext jaxbContext = JAXBContext.newInstance(wrapper.getClass());
		Marshaller marshaller = jaxbContext.createMarshaller();

		//Ausgaben
//		client.addFilter(new LoggingFilter(System.out));
//		marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

		StringWriter sw = new StringWriter();
		marshaller.marshal(wrapper, sw);

		MultivaluedMap<String, String> map = new MultivaluedMapImpl();
		map.add("xml", sw.toString());

		logger.trace("sende HTTP Post:");
		logger.trace("URL:{}", webservice.getUrl());
		logger.trace("String: {}", sw);
		long startTime = System.currentTimeMillis();

		wrapper = webResource.post(wrapper.getClass(), map);
		long duration = System.currentTimeMillis() - startTime;
		if(logger.isTraceEnabled()){
			logger.trace("Erhaltene Antwort: "+wrapper);
		}
		logger.debug("{} erfolgreich in {}ms geschrieben",
				webservice.getEntityName(), duration);
		return wrapper;
	}

	public void createTag() {
		PrestaTagWrapper wrapper = new PrestaTagWrapper();
		wrapper = (PrestaTagWrapper) loadEntities(wrapper,
				PrestaWebservice.EMPTY_TAG);
		((PrestaTag) wrapper.getTag()).setName("testtag");
		((PrestaTag) wrapper.getTag()).setId_lang("1");
		try {
			wrapper = (PrestaTagWrapper) createEntity(PrestaWebservice.CREATE_TAG, wrapper);
		} catch (Exception e) {
			logger.error("{} konnte nicht erstellt werden, Ursache: {}",PrestaWebservice.CREATE_TAG.getEntityName(), e.getMessage());
		} 
	}

}
